package com.example.networklab.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.example.networklab.common.BizException;
import com.example.networklab.common.ExceptionEnum;
import com.example.networklab.domain.po.User;
import com.example.networklab.domain.req.AddUserReq;
import com.example.networklab.domain.req.EditSelfReq;
import com.example.networklab.domain.req.LoginReq;
import com.example.networklab.domain.req.RegisterBatchReq;
import com.example.networklab.domain.vo.LoginVO;
import com.example.networklab.enums.UserRole;
import com.example.networklab.mapper.UserMapper;
import com.example.networklab.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.networklab.util.PasswordUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author dzw
 * @since 2025-02-26
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Override
    public LoginVO login(LoginReq loginReq) {
        User user = this.lambdaQuery()
                .eq(User::getUsername, loginReq.getUsername())
                .eq(User::getPassword, PasswordUtil.encryptPassword(loginReq.getPassword())).one();
        if (user == null) {
            throw new BizException(ExceptionEnum.LOGIN_ERROR);
        }
        StpUtil.login(user.getUserId());
        LoginVO loginVO = new LoginVO();
        BeanUtil.copyProperties(user, loginVO);
        loginVO.setSatoken(StpUtil.getTokenValue());
        return loginVO;
    }

    @Override
    public boolean exist(String username) {
        return this.lambdaQuery().eq(User::getUsername, username).count() > 0;
    }

    @Override
    public void editSelf(EditSelfReq editSelfReq) {
        if (StrUtil.isEmpty(editSelfReq.getOldPassword()) || StrUtil.isEmpty(editSelfReq.getNewPassword())) {
            throw new BizException(ExceptionEnum.PARAM_ERROR);
        }
        User user = this.getById(StpUtil.getLoginIdAsLong());
        if (!PasswordUtil.encryptPassword(editSelfReq.getOldPassword()).equals(user.getPassword())) {
            throw new BizException(ExceptionEnum.OLD_PASSWORD_ERROR);
        }
        user.setPassword(PasswordUtil.encryptPassword(editSelfReq.getNewPassword()));
        if (StrUtil.isNotEmpty(editSelfReq.getName())) {
            user.setName(editSelfReq.getName());
        }
        this.updateById(user);
        StpUtil.logout();
    }

    @Override
    public void register(AddUserReq addUserReq) {
        if (this.exist(addUserReq.getUsername())) {
            throw new BizException(ExceptionEnum.USERNAME_EXIST);
        }
        User user = new User();
        BeanUtil.copyProperties(addUserReq, user);
        user.setPassword(PasswordUtil.encryptPassword(addUserReq.getPassword()));
        this.save(user);
    }

    @Transactional
    @Override
    public void registerBatch(RegisterBatchReq registerBatchReq) {
        ArrayList<User> users = new ArrayList<>();
        for (String username : registerBatchReq.getList()) {
            User user = new User();
            user.setUsername(username);
            user.setPassword(PasswordUtil.encryptPassword(username));
            user.setName(username);
            user.setRole(UserRole.STUDENT);
            user.setGrade(registerBatchReq.getGrade());
            user.setClassNum(registerBatchReq.getClassNum());
            users.add(user);
        }
        this.saveBatch(users);
    }

    @Override
    public Integer countStudentsInClass(Integer grade, Integer classNum) {
        Long count = this.lambdaQuery()
                .eq(User::getGrade, grade)
                .eq(User::getClassNum, classNum)
                .count();
        return count.intValue();
    }
}
